﻿namespace Guia.Elements
{
    using System;
    using System.Collections.Generic;
    using System.Windows.Automation;
    using Config;
    using Core;
    using Locator;

    /// <summary>
    /// This class represents a (WinForms) MessageBox.
    /// </summary>
    public class MessageBox : UiElement
    {
        /// <summary>
        /// Initializes a new instance of the MessageBox class. 
        /// </summary>
        /// <param name="automationElement">The AutomationElement representating the MessageBox.</param>
        public MessageBox(AutomationElement automationElement)
            : base(automationElement)
        {
        }

        /// <summary>
        /// The possible MessageBox types.
        /// </summary>
        public enum EMessageBoxType
        {
            /// <summary>
            /// MessageBox with an Ok button.
            /// </summary>
            OK,

            /// <summary>
            /// MessageBox with an Ok and a Cancel button.
            /// </summary>
            OK_CANCEL,

            /// <summary>
            /// MessageBox with a Yes and a No button.
            /// </summary>
            YES_NO,

            /// <summary>
            /// MessageBox with a Yes, a No and a Cancel button.
            /// </summary>
            YES_NO_CANCEL,

            /// <summary>
            /// Unknown MessageBox type
            /// </summary>
            UNKNOWN
        }

        /// <summary>
        /// Gets the default-condition to find a control by its type.
        /// </summary>
        public static SearchCondition ControlTypeCondition
        {
            get
            {
                return SearchCondition.ByControlType(ControlType.Window);
            }
        }

        /// <summary>
        /// Gets the text inside of the MessageBox.
        /// </summary>
        public string Text
        {
            get
            {
                Label[] allLabels = UiElementFactory.GetAllUiElements<Label>(this);
                return allLabels[0].TextValue;
            }
        }

        /// <summary>
        /// Gets the buttons inside of the MessageBox.
        /// </summary>
        public Button[] Buttons
        {
            get
            {
                return UiElementFactory.GetAllUiElements<Button>(this);
            }
        }

        /// <summary>
        /// Gets the MessageBoxType.
        /// </summary>
        public EMessageBoxType MessageBoxType
        {
            get
            {
                EMessageBoxType result = EMessageBoxType.UNKNOWN;
                List<Button> buttons = new List<Button>(this.Buttons);

                // minus 1 because of the window close button
                switch (buttons.Count - 1)
                {
                    case 1:
                        result = EMessageBoxType.OK;
                        break;
                    case 2:
                        {
                            bool existsOk =
                                buttons.Exists(
                                    b => b.AutomationId == "1");
                            bool existsCancel =
                                buttons.Exists(
                                    b => b.AutomationId == "2");
                            if (existsOk && existsCancel)
                            {
                                result = EMessageBoxType.OK_CANCEL;
                            }
                            else
                            {
                                result = EMessageBoxType.YES_NO;
                            }
                        }

                        break;
                    case 3:
                        result = EMessageBoxType.YES_NO_CANCEL;
                        break;
                }

                return result;
            }
        }

        /// <summary>
        /// Invokes the OK button.
        /// </summary>
        /// <exception cref="OperationNotSupportedException">
        /// </exception>
        public void Ok()
        {
            if (this.MessageBoxType == EMessageBoxType.OK)
            {
                this.Get<Button>(
                    SearchCondition.ByAutomationId("2")).Invoke();
            }
            else if (this.MessageBoxType == EMessageBoxType.OK_CANCEL)
            {
                this.Get<Button>(
                    SearchCondition.ByAutomationId("1")).Invoke();
            }
            else
            {
                throw new OperationNotSupportedException("Invalid MessageBoxType " + this.MessageBoxType);
            }
        }

        /// <summary>
        /// Invokes the Cancel button.
        /// </summary>
        /// <exception cref="OperationNotSupportedException">
        /// </exception>
        public void Cancel()
        {
            if (this.MessageBoxType == EMessageBoxType.OK_CANCEL || this.MessageBoxType == EMessageBoxType.YES_NO_CANCEL)
            {
                this.Get<Button>(
                    SearchCondition.ByAutomationId("2")).Invoke();
            }
            else
            {
                throw new OperationNotSupportedException("Invalid MessageBoxType " + this.MessageBoxType);
            }
        }

        /// <summary>
        /// Invokes the Yes button.
        /// </summary>
        /// <exception cref="OperationNotSupportedException">
        /// </exception>
        public void Yes()
        {
            if (this.MessageBoxType == EMessageBoxType.YES_NO || this.MessageBoxType == EMessageBoxType.YES_NO_CANCEL)
            {
                this.Get<Button>(
                    SearchCondition.ByAutomationId("6")).Invoke();
            }
            else
            {
                throw new OperationNotSupportedException("Invalid MessageBoxType " + this.MessageBoxType);
            }
        }

        /// <summary>
        /// Invokes the No button.
        /// </summary>
        /// <exception cref="OperationNotSupportedException">
        /// </exception>
        public void No()
        {
            if (this.MessageBoxType == EMessageBoxType.YES_NO || this.MessageBoxType == EMessageBoxType.YES_NO_CANCEL)
            {
                this.Get<Button>(
                    SearchCondition.ByAutomationId("7")).Invoke();
            }
            else
            {
                throw new OperationNotSupportedException("Invalid MessageBoxType " + this.MessageBoxType);
            }
        }
    }
}
